package com.nightonke.boommenu.Animation;

import ohos.agp.components.StackLayout;
import ohos.app.Context;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.components.Component;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;

import com.nightonke.boommenu.BoomMenuButton;
import com.nightonke.boommenu.Util;

import java.util.ArrayList;


/**
 * Created by Weiping Huang at 01:21 on 16/12/2
 * For Personal Open Source
 * Contact me at 2584541288@qq.com or nightonke@outlook.com
 */

public class ShareLinesView extends Component {

    private long animationShowDelay1;
    private long animationShowDuration1;
    private long animationShowDelay2;
    private long animationShowDuration2;
    private long animationShowDelay3;
    private long animationShowTotalDuration;

    private long animationHideDelay1;
    private long animationHideDuration1;
    private long animationHideDelay2;
    private long animationHideDuration2;
    private long animationHideDelay3;
    private long animationHideTotalDuration;

    private float processForLine1 = 1;
    private float processForLine2 = 1;

    private ArrayList<Point> piecePositions;

    private Color line1Color = Color.WHITE;
    private Color line2Color = Color.WHITE;
    private float lineWidth = 3;

    private Paint linePaint;

    public ShareLinesView(Context context) {
        super(context);
        linePaint = new Paint();
        linePaint.setAntiAlias(true);
        addDrawTask(new DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                Point start1 = new Point(piecePositions.get(1).getPointX(), piecePositions.get(1).getPointY());
                Point end1 = new Point((piecePositions.get(0).getPointX() - piecePositions.get(1).getPointX()) * processForLine1 + piecePositions.get(1).getPointX(), (piecePositions.get(0).getPointY() - piecePositions.get(1).getPointY()) * processForLine1 + piecePositions.get(1).getPointY());
                canvas.drawLine(start1, end1, linePaint);
                linePaint.setColor(line2Color);

                Point start2 = new Point(piecePositions.get(2).getPointX(), piecePositions.get(2).getPointY());
                Point end2 = new Point((piecePositions.get(1).getPointX() - piecePositions.get(2).getPointX()) * processForLine2 + piecePositions.get(2).getPointX(), (piecePositions.get(1).getPointY() - piecePositions.get(2).getPointY()) * processForLine2 + piecePositions.get(2).getPointY());
                canvas.drawLine(start2, end2, linePaint);
            }
        });
    }

    /**
     * setData
     * @param piecePositionsIn
     * @param bmb
     */
    public void setData(ArrayList<RectFloat> piecePositionsIn, BoomMenuButton bmb) {
        float xOffset = bmb.getDotRadius() - lineWidth / 4f;
        float yOffset = (float) (bmb.getDotRadius()  - lineWidth * Math.sqrt(3) / 4f) + Util.dp2px(0.25f);

        this.piecePositions = new ArrayList<>();
        for (RectFloat piecePosition : piecePositionsIn) {
            boolean existed = false;
            for (Point p : this.piecePositions) {
                if (p.equals(piecePosition.left, piecePosition.top)) {
                    existed = true;
                    break;
                }
            }
            if (!existed) this.piecePositions.add(new Point(piecePosition.left, piecePosition.top));
        }
        for (Point piecePosition : this.piecePositions) piecePosition.translate(xOffset, yOffset);

        int[] pieceNumbers = new int[3];
        int pieceNumber = piecePositions.size();
        for (int i = 0; i < pieceNumber; i++) pieceNumbers[i % 3]++;
        animationShowDelay1 = bmb.getShowDelay() * (pieceNumbers[0] - 1);
        animationShowDuration1 = pieceNumbers[0] * bmb.getShowDelay();
        animationShowDelay2 = (pieceNumbers[0] - 1 + pieceNumbers[1]) * bmb.getShowDelay();
        animationShowDuration2 = (pieceNumbers[0] + pieceNumbers[1]) * bmb.getShowDelay();
        animationShowDelay3 = bmb.getShowDelay() * (pieceNumbers[2] - 1 + pieceNumbers[1] + pieceNumbers[0]) + bmb.getShowDuration();
        animationShowTotalDuration = animationShowDelay3;

        animationHideDelay1 = (pieceNumbers[2] - 1) * bmb.getHideDelay() + bmb.getHideDuration();
        animationHideDuration1 = (pieceNumbers[2]) * bmb.getHideDelay()  + bmb.getHideDuration();
        animationHideDelay2 = bmb.getHideDelay() * (pieceNumbers[2] - 1 + pieceNumbers[1]) + bmb.getHideDuration();
        animationHideDuration2 = (pieceNumbers[2] + pieceNumbers[1]) * bmb.getHideDelay()  + bmb.getHideDuration();
        animationHideDelay3 = bmb.getHideDelay() * (pieceNumbers[2] - 1 + pieceNumbers[1] + pieceNumbers[0]) + bmb.getHideDuration();
        animationHideTotalDuration = animationHideDelay3;
    }

    /**
     * setShowProcess
     * @param process
     */
    public void setShowProcess(float process) {
        long current = (long) (process * animationShowTotalDuration);
        if (animationShowDelay1 < current && current <= animationShowDuration1) {
            processForLine1 = (animationShowDuration1 - current)
                    / (float)(animationShowDuration1 - animationShowDelay1);
        } else if (animationShowDuration1 < current && current <= animationShowDelay2) {
            processForLine1 = 0;
        } else if (animationShowDelay2 < current && current <= animationShowDuration2) {
            processForLine2 = (animationShowDuration2 - current)
                    / (float)(animationShowDuration2 - animationShowDelay2);
        } else if (animationShowDuration2 <= current) {
            processForLine1 = 0;
            processForLine2 = 0;
        }
        invalidate();
    }

    /**
     * setHideProcess
     * @param process
     */
    public void setHideProcess(float process) {
        long current = (long) (process * animationHideTotalDuration);
        if (animationHideDelay1 < current && current <= animationHideDuration1) {
            processForLine2 = 1 - (animationHideDuration1 - current)
                    / (float)(animationHideDuration1 - animationHideDelay1);
        } else if (animationHideDuration1 < current && current <= animationHideDelay2) {
            processForLine2 = 1;
        } else if (animationHideDelay2 < current && current <= animationHideDuration2) {
            processForLine1 = 1 - (animationHideDuration2 - current)
                    / (float)(animationHideDuration2 - animationHideDelay2);
        } else if (animationHideDuration2 <= current) {
            processForLine1 = 1;
            processForLine2 = 1;
        }
        invalidate();
    }

    /**
     * set Line1Color
     * @param line1ColorIn
     */
    public void setLine1Color(Color line1ColorIn) {
        this.line1Color = line1ColorIn;
        linePaint.setColor(line1ColorIn);
    }

    /**
     * set Line2Color
     * @param line2ColorIn
     */
    public void setLine2Color(Color line2ColorIn) {
        this.line2Color = line2ColorIn;
    }

    /**
     * set LineWidth
     * @param lineWidthIn
     */
    public void setLineWidth(float lineWidthIn) {
        this.lineWidth = lineWidthIn;
        linePaint.setStrokeWidth(lineWidthIn);
    }

    /**
     * place
     * @param left
     * @param top
     * @param width
     * @param height
     */
    public void place(int left, int top, int width, int height) {
        StackLayout.LayoutConfig layoutParams = (StackLayout.LayoutConfig) getLayoutConfig();
        if (layoutParams != null) {
            layoutParams.setMarginLeft(left);
            layoutParams.setMarginTop(top);
            layoutParams.width = width;
            layoutParams.height = height;
            setLayoutConfig(layoutParams);
        }
    }
}
